from sys import exit
from random import randint 
from textwrap import dedent
import numpy as np
'''房间
战斗发生在引擎
英雄信息记录在引擎上，经询问获得hero_kind变量，存储，在Engine中生成英雄对象，通过该变量获得英雄信息
怪物生成在每个room，所以room得返回怪物信息
怪物的生成，也可以在引擎，利用一个随机数，randint(0,1),为1则生成，否则没有怪物，实现在进入每个房间之前的随机战斗
上面两种模式，设计意图，取决于是想在指定房间遇怪，还是全部随机遇怪
'''
class Engine(object):
	def __init__(self,map,hero_choice):
		self.map = map
		self.hero = Hero()
		self.hero_kind = hero_choice
		self.evils = Evil()
		self.dead = Dead()
		self.award = Award()
		
	def hero_info_create(self):
		print(dedent("\nBelow is your hero information"))
		hero_life = self.hero.get_hero_life(self.hero_kind)
		hero_attack = self.hero.compute_hero_attack(self.hero_kind)[2]
		hero_defense = self.hero.compute_hero_defense(self.hero_kind)[2]
		
		
		#print("-"* 10,"检验英雄信息中","-" * 10)
		print("-"* 10,"初始化英雄信息","-"*10)
		print(dedent(f"""
		英雄种属:{self.hero_kind}
		英雄血量:{hero_life}
		英雄攻击力:{hero_attack}
		英雄防御力:{hero_defense}	
		"""))
		#print("-"* 10,"战斗进行中","-" * 10)
		print("Let's go!")
		return hero_life,hero_attack,hero_defense
		
	def evil_info(self):		
		evil_num = randint(2,4)
		evil_kind = self.evils.evil_kind[randint(0,2)]
		evil_life = self.evils.get_evil_life(evil_kind)
		evil_attack = self.evils.get_evil_attack(evil_kind)
		
		print(dedent("""
			you encounter some evils who guard the door of the next room.
			Are you ready to battle with them? Go!\n"""))	
		
		print("-"* 10,"检验怪物信息中","-" * 10)
		print(dedent(f"""
				怪物等级:{evil_kind}
				怪物数量:{evil_num}
				怪物血量:{evil_life}
				怪物攻击力:{evil_attack}
				"""))	
		print("-"* 10,"检验怪物信息完毕","-" * 10)
		return evil_num,evil_life,evil_attack
		
		
	def battle(self,hero_life,hero_attack,hero_defense):
		evil_num,evil_life,evil_attack = self.evil_info() #初始化怪物
		print("\n")
		print("-"* 10,"检验英雄当前信息","-" * 10)
		print(dedent(f"""
		英雄血量:{hero_life}
		英雄攻击力:{hero_attack}
		英雄防御力:{hero_defense}	
		"""))
		print("-"* 10,"检验英雄当前信息完毕","-" * 10)
		print("\n")
		print('-'*10,"进入战斗",'-'*10)
		round = 1
		
		for i in range(1,evil_num + 1):
			single_evil_life = evil_life
			while single_evil_life > 0:
				print(dedent(f"""-----------第{round}回合----------"""))
				if  evil_attack - hero_defense < 0:
					round_attack_evil = 0
				else:
					round_attack_evil = (evil_attack - hero_defense)* (evil_num-i+1)
					
				round_attack_hero = hero_attack
				
				single_evil_life -= round_attack_hero
				hero_life -= round_attack_evil
				
				if single_evil_life < 0 :
					single_evil_life = 0
					
				if hero_life < 0:
					hero_life = 0
					
				print(dedent(f"""
						{evil_num-i+1}只怪物对英雄造成总伤害:{round_attack_evil}
						英雄对第{i}只怪物造成伤害:{round_attack_hero}
						第{i}只怪物剩余血量:{single_evil_life}
						英雄剩余血量:{hero_life}\n"""))
						
				if hero_life == 0:
					return self.dead.dead('battle lose')
				else:
					round += 1
					
		print('-'*10,"战斗结束",'-'*10)
		return hero_life,hero_attack,hero_defense
					
	def awards(self):
		print("Then you will get the award I made just for you!")
		print("I know that you must be happy for that!")
		print("Here are the awards,choose one you like!\n")
		print(f"{','.join(self.award.awards)}")
		choose = input("input the number of the awards >:")
		if choose.isdigit():
			choose_num = int(choose)-1
			print(f"Ok,you pick the one,{self.award.awards[choose_num]}")
			exit(0)
		else:
			print("Please input the number!")
			return self.awards()
			
	def play(self):
		hero_life,hero_attack,hero_defense = self.hero_info_create()	#初始化英雄
		
		current_room = self.map.opening_room()
		final_room = self.map.next_room("finishedroom")
		
		while current_room != final_room:
			#最好方法是用正态分布，去构成一个概率，即用Z值大于一个数值，概率可随意定
			normal_digit = np.random.normal(0,1.0)
			if normal_digit < 0.67:#一个标准正态分布的数，<0.67的概率是75%
			#if randint(0,1) == 1 :
				#进入战斗阶段
				hero_life,hero_attack,hero_defense = self.battle(hero_life,hero_attack,hero_defense)					
			else:
				pass
			next_room_name= current_room.enter()
			current_room = self.map.next_room(next_room_name)
						
		current_room.enter()
		self.awards()
			
			
class Award(object):
	awards = ['listen a song I song for you ','A promise whatever you ask','A gift not too much expensive']
			
			
class Dead(object):
	dead_reason_out = {"take money":"The bear look at you then slaps your face.","taunt bear":"The bear gets pissed of and chews your leg.","head":"Well that was tasty!","no condition":"You stumble around the room until you starve.","too much":"You greedy bastard!","no number":"Man,learn to type a number","battle lose":"You're hitted by the evils.Sad!"}
	def dead(self,reason):
		print("\n")
		print(self.dead_reason_out.get(reason))
		print("You loser!")
		exit(1)


class Evil(object):
	#怪物种类为ket，值为一个列表，分别为怪物血量，怪物攻击力
	evils = {'low':[25,30],'middle':[30,30],'high':[40,35]}
	evil_kind = ['low','middle','high']
	def get_evil_life(self,evil_kind):
		return self.evils.get(evil_kind)[0]
	
	def get_evil_attack(self,evil_kind):
		return self.evils.get(evil_kind)[1]


class Equipment(object):
	#玩家配置的装备的攻击力，防御力在这里查询
	equipments_kind = ['hand','arrow','claw']
	equipments_info = {'hand':[5,5],'arrow':[15,10],'claw':[15,15]}
	def get_equipment_attack(self,equipments_kind):
		return self.equipments_info.get(equipments_kind)[0]
	
	def get_equipment_defense(self,equipments_kind):
		return self.equipments_info.get(equipments_kind)[1]
	
class Hero(object):
	#每次游戏开始前，玩家可以选择一个Hero冒险
	#Hero 和 evil 一样具有不同的属性。
	#hero_equip 包括Hero 血量，Hero配备武器
	#hero_info 包括hero 本身攻击力、防御力
	hero_equip = {'Human':[500,'hand'],'Angel':[800,'arrow'],'Demon':[600,'claw']}
	hero_info = {'Human':[10,15],'Angel':[5,15],'Demon':[15,5]}
	hero_kind = ['Human','Angel','Demon']

	def __init__(self):
		self.equipment = Equipment() 
		
	def get_hero_life(self,hero_kind):
		return self.hero_equip.get(hero_kind)[0]
	
	def get_hero_attack(self,hero_kind):
		return self.hero_info.get(hero_kind)[0]
	
	def get_hero_defense(self,hero_kind):
		return self.hero_info.get(hero_kind)[1]
	
	def get_hero_equip(self,hero_kind):
		return self.hero_equip.get(hero_kind)[1]
	
	def compute_hero_attack(self,hero_kind):
		hero_equip = self.get_hero_equip(hero_kind)
		equip_attack = self.equipment.get_equipment_attack(hero_equip)
		hero_attack =self.get_hero_attack(hero_kind)
		
		attack_sum = equip_attack + hero_attack
		return equip_attack,hero_attack,attack_sum
	
	def compute_hero_defense(self,hero_kind):
		hero_equip = self.get_hero_equip(hero_kind)
		equip_defense = self.equipment.get_equipment_defense(hero_equip)
		hero_defense = self.get_hero_defense(hero_kind)
		
		defense_sum = hero_defense + equip_defense
		return equip_defense,hero_defense,defense_sum
		
	def create_hero(self,hero_kind):
		return self.hero_name_object(hero_kind)
		
	
		
	
class Room(object):
	def __init__(self):
		self.deadscene = Dead()
		self.evils = Evil()
		
	def enter(self):
		exit(1)
				
		
class FinishedRoom(Room):


	def enter(self):
		print("\nNice ,you're not greedy,you win!")
		

		
class StartRoom(Room):

	
	def enter(self):
		print(dedent("""
		You now are in a dark room.
		There is a door to your right and left.
		Which one do you take?
		Just input 'left' or 'right'. 
		"""))
		
		choice = input("Tell me your choice:> ")
		if choice == 'left':
			return 'bearroom'
		elif choice == 'right':
			return 'cthulhuroom'
		else:
			choice = 'no condition'
			return self.deadscene.dead(choice)

			
class BearRoom(Room):
		
	def enter(self):
		print(dedent("""
		You have arrived another room.
		But sorry for that,
		there is a bear.
		The bear has a bunch of honey.
		The fat bear is in front of another door.
		How are you going to move the bear?
		"""))
		
		bear_moved = False
		
		while True:
			choice = input ("take money or taunt bear or open door :> ")		
			if choice == "take money":
				return self.deadscene.dead(choice)
			elif choice == "taunt bear" and (not bear_moved):
				print("The bear has moved from the door.")
				print("You can go through it now.")
				bear_moved = True
			elif choice == "taunt bear" and bear_moved:
				return self.deadscene.dead(choice)
			elif choice == "open door" and bear_moved:
				return 'goldroom'
			else:
				return 'bearroom'
	
class GoldRoom(Room):

	def enter(self):
		
		print("This room is full of gold. How much do you take?")
		
		choice = input("input whatever number you like,no limit:> ")
		
		if choice.isdigit():
			how_much = int(choice)
		else:
			choice = 'no number'
			return self.deadscene.dead(choice)
		
		if how_much < 50:
			return  'finishedroom'
		else:
			choice = 'too much'
			return self.deadscene.dead(choice)
			

class CthulhuRoom(Room):

	def enter(self):
		print(dedent("""
		Here you see the great evil Cthulhu.
		He ,it, whatever stares at you and you go insane.
		Do you flee for your life or eat your head?
		"""))
		
		choice = input("flee or head:> ")
		
		if choice == "flee":
			return 'startroom'
		elif choice == "head":
			return self.deadscene.dead(choice)
		else:
			return 'cthulhuroom'

class Map(object):
	rooms = {"goldroom":GoldRoom(),"bearroom":BearRoom(),"cthulhuroom":CthulhuRoom(),"finishedroom":FinishedRoom(),"startroom":StartRoom()}
	
	def __init__(self,startroom):
		self.startroom = startroom
	def next_room(self,next_room_name):
		return  self.rooms.get(next_room_name)
		
	def opening_room(self):
		return self.next_room(self.startroom) 		


class Get_hero(object):
	def __init__(self):
		self.hero = Hero()
	def get_hero_choice(self):
		print(dedent("""
			My player,before you start the adventure,
			I'll want to give you some information.
			You'll encounter some evils when you go through the doors.\n
			So,please choose a hero to accompany you in the adventure.
			The hero will help you to battle with the evil.
			But be careful ,if hero dies in the battle ,then the game over.
			Let's choose!
			"""))
		print("-"*10)
		for hero in self.hero.hero_kind:
			print(dedent(f"""
				Hero:{hero} hero_life:{self.hero.get_hero_life(hero)}
				equip:{self.hero.get_hero_equip(hero)} 
				attack:{self.hero.compute_hero_attack(hero)[2]}
				defense:{self.hero.compute_hero_defense(hero)[2]}
				"""))
			print('-'*10)
		print("Please choose your hero.")
		hero_choice = input(f"\n{','.join(self.hero.hero_kind)}>: ")
		
		#print(hero_choice)
		return hero_choice
		

hero = Get_hero()
hero_choice = hero.get_hero_choice() 
map1 = Map('startroom')
game1 = Engine(map1,hero_choice)
game1.play()

	

